<script setup lang="ts">
  import { computed, CSSProperties, PropType, ref } from 'vue'
  import { CustomProcessNode } from '../hooks/types'

  defineOptions({
    name: 'OrderCustomProcessNodeList',
  })

  const props = defineProps({
    nodeList: {
      type: Array as PropType<Array<CustomProcessNode>>,
      required: true,
    },
  })

  const emits = defineEmits<{
    (e: 'node-click', value: CustomProcessNode | null): void
    (e: 'add-node-click', value: number): void
    (e: 'node-del-click', value: number): void
  }>()

  const lineItemDivList = ref<Array<HTMLElement>>([])
  const nodeItemDivList = ref<Array<HTMLDivElement>>([])
  const nodeListDiv = ref<HTMLDivElement | null>(null)
  const nodeItemStyleVariable = {
    height: 40,
    width: 160,
  }
  const nodeListStyleVariable = {
    rowGap: 160,
  }
  const orderCustomProcessNodeListStyleVariable = {
    paddingt: 24,
    paddingl: 72,
    paddingr: 24,
    paddingb: 24,
  }
  const nodeListStyle = computed<CSSProperties>(() => {
    return {
      height: `${
        props.nodeList.length * nodeItemStyleVariable.height +
        (props.nodeList.length - 1) * nodeListStyleVariable.rowGap
      }px`,
      rowGap: `${nodeListStyleVariable.rowGap}px`,
    }
  })
  const foreignObjectStyleVariable = {
    height: 40,
    width: 40,
  }
  const addNodeBtnStyle: CSSProperties = {
    width: `${foreignObjectStyleVariable.width}px`,
    height: `${foreignObjectStyleVariable.height}px`,
    top: `${
      foreignObjectStyleVariable.height +
      nodeListStyleVariable.rowGap / 2 -
      foreignObjectStyleVariable.width / 2
    }px`,
    left: `${nodeItemStyleVariable.width / 2 - foreignObjectStyleVariable.width / 2}px`,
  }
  const orderCustomProcessNodeListStyle: CSSProperties = {
    paddingTop: `${orderCustomProcessNodeListStyleVariable.paddingt}px`,
    paddingLeft: `${orderCustomProcessNodeListStyleVariable.paddingl}px`,
    paddingRight: `${orderCustomProcessNodeListStyleVariable.paddingr}px`,
    paddingBottom: `${orderCustomProcessNodeListStyleVariable.paddingb}px`,
  }
  const activeNode = ref<CustomProcessNode | null>(null)

  const handleNodeClick = (node: CustomProcessNode) => {
    activeNode.value = node
    emits('node-click', activeNode.value)
  }

  const getPathDAndPolygonPoints = (lineIndex: number) => {
    if (!nodeListDiv.value) {
      return {
        path: '',
        polygon: '',
      }
    }

    if (lineItemDivList.value.length <= 0) {
      return {
        path: '',
        polygon: '',
      }
    }

    if (nodeItemDivList.value.length <= 0) {
      return {
        path: '',
        polygon: '',
      }
    }

    const node = nodeItemDivList.value[lineIndex]
    if (!node) {
      return {
        path: '',
        polygon: '',
      }
    }

    const startX = node.offsetLeft + node.offsetWidth / 2
    const startY =
      (lineIndex + 1) * nodeItemStyleVariable.height +
      lineIndex * nodeListStyleVariable.rowGap +
      orderCustomProcessNodeListStyleVariable.paddingt

    const targetX = startX
    const targetY = startY + nodeListStyleVariable.rowGap

    return {
      path: `M ${startX} ${startY} L ${targetX} ${targetY}`,
      polygon: `${targetX},${targetY} ${targetX - 5},${targetY - 10} ${targetX + 5},${
        targetY - 10
      }`,
    }
  }

  const onOrderCustomProcessContainerClick = () => {
    activeNode.value = null
    emits('node-click', activeNode.value)
  }

  const handleAddNodeClick = (nodeIndex: number) => {
    emits('add-node-click', nodeIndex)
  }

  const handleNodeDelClick = (nodeIndex: number) => {
    emits('node-del-click', nodeIndex)
  }
</script>

<template>
  <div
    class="order-custom-process-node-list"
    :style="orderCustomProcessNodeListStyle"
    @click="onOrderCustomProcessContainerClick"
  >
    <svg>
      <g
        v-for="(line, lineIndex) in props.nodeList.filter(
          (item, index) => index !== props.nodeList.length - 1,
        )"
        :key="lineIndex"
      >
        <path
          ref="lineItemDivList"
          :d="getPathDAndPolygonPoints(lineIndex).path"
          class="line"
        ></path>
        <polygon
          stroke-width="10"
          :points="getPathDAndPolygonPoints(lineIndex).polygon"
          stroke-linejoin="round"
          class="end-polygon"
        ></polygon>
      </g>
    </svg>
    <div ref="nodeListDiv" class="node-list" :style="nodeListStyle">
      <template v-for="(node, nodeIndex) in props.nodeList" :key="nodeIndex">
        <div
          ref="nodeItemDivList"
          class="node-item"
          :style="{
            transform: `translate(0, ${
              nodeIndex * (nodeItemStyleVariable.height + nodeListStyleVariable.rowGap)
            }px)`,
            height: `${nodeItemStyleVariable.height}px`,
            width: `${nodeItemStyleVariable.width}px`,
          }"
          @click.stop="handleNodeClick(node)"
        >
          <div
            :class="{
              'node-item-container': true,
              'node-item-container-active': activeNode && activeNode.id === node.id,
            }"
          >
            <div class="label-container">
              <div v-if="node.isStart" class="icon-start">
                <i class="iconfont icon-kehuziliao"></i>
              </div>
              <div v-else-if="node.isEnd" class="icon-end">
                <i class="iconfont icon-qiyong2"></i>
              </div>
              <div v-else class="icon">
                <i class="iconfont icon-gaizhang1"></i>
              </div>
              <div class="label">{{ node.name }}</div>
            </div>

            <div class="del-btn">
              <i
                v-if="!node.isStart && !node.isEnd"
                class="iconfont icon-shanchu2"
                @click.stop="handleNodeDelClick(nodeIndex)"
              ></i>
            </div>
          </div>
          <div
            v-if="nodeIndex !== props.nodeList.length - 1"
            class="add-node-btn"
            :style="addNodeBtnStyle"
            @click.stop="handleAddNodeClick(nodeIndex)"
          >
            <i class="iconfont icon-tianjia1"></i>
          </div>
        </div>
      </template>
    </div>
  </div>
</template>

<style scoped lang="scss">
  .order-custom-process-node-list {
    width: 100%;
    height: 100%;
    background: #f5f6f8;
    position: relative;
    zoom: 1;
    overflow: auto;
    box-sizing: border-box;
    padding: 24px;

    svg {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      overflow: visible;

      .line {
        fill: none;
        stroke: #c8cdd4;
        stroke-width: 2px;
      }

      .end-polygon {
        fill: #c8cdd4;
        stroke: #c8cdd4;
        stroke-width: 2px;
      }
    }

    .node-list {
      width: 100%;
      display: flex;
      flex-direction: column;

      .node-item {
        background-color: #fff;
        border-radius: 40px;
        box-shadow: 0 1px 2px 1px rgba(6, 30, 53, 0.1);
        position: absolute;
        cursor: pointer;
        box-sizing: border-box;

        .node-item-container-active {
          box-shadow: 0 0 0 2px rgba($color: #007cff, $alpha: 1) inset !important;
        }

        .node-item-container {
          padding: 8px 16px;
          width: 100%;
          height: 100%;
          box-sizing: border-box;
          display: flex;
          align-items: center;
          justify-content: space-between;
          transition: all 0.1s ease-in-out;
          border-radius: 10000px;

          &:hover {
            box-shadow: 0 0 0 1px rgba($color: #007cff, $alpha: 1) inset,
              0 0 0 4px rgba($color: #007cff, $alpha: 0.15);
          }

          .label-container {
            display: flex;
            align-items: center;
            column-gap: 8px;

            .icon-start {
              .iconfont {
                color: #00c0c0;
                font-size: 12px;
              }
            }

            .icon-end {
              .iconfont {
                color: #606266;
                font-size: 12px;
              }
            }

            .icon {
              .iconfont {
                color: #007cff;
                font-size: 12px;
              }
            }

            .label {
              color: #333;
              font-size: 14px;
            }
          }

          .del-btn {
            .iconfont {
              font-size: 12px;
              cursor: pointer;

              &:hover {
                color: #f56c6c;
              }
            }
          }
        }

        .add-node-btn {
          position: absolute;
          background-color: #fff;
          border-radius: 100000px;
          box-shadow: 0 1px 2px 1px rgba(6, 30, 53, 0.1);
          cursor: pointer;
          transition: all 0.1s ease-in;
          display: flex;
          justify-content: center;
          align-items: center;
          color: #007cff;

          &:hover {
            background-color: #007cff;
            color: #fff;
            box-shadow: none;
          }
        }
      }
    }
  }
</style>
